package com.summer.study.leetcode.thread.foobar_115;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @auther: 杨杰
 * @date: 2019/7/25 11:29
 * @description:
 */
public class ReentrantLockDemo {

    private int n;

    public ReentrantLockDemo(int n) {
        this.n = n;
    }

    private ReentrantLock lock = new ReentrantLock();

    private Condition c1 = lock.newCondition();

    private Condition c2 = lock.newCondition();

    private volatile boolean isFirst = true;

    public void foo(Runnable printFoo) throws InterruptedException {
        for (int i = 0; i < n; i++) {
            lock.lock();
            try {
                //不是轮到foo打印的话，线程等待
                while (!isFirst) {
                    c1.await();
                }
                //printFoo.run();
                System.out.println("foo");
                isFirst = false;
                //唤醒打印bar的线程
                c2.signal();
            } finally {
                lock.unlock();
            }
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        for (int i = 0; i < n; i++) {
            lock.lock();
            try {
                while (isFirst) {
                    c2.await();
                }
                //printBar.run();
                System.out.println("bar");
                isFirst = true;
                c1.signal();
            } finally {
                lock.unlock();
            }

        }
    }

    public static void main(String[] args) throws InterruptedException{
        ReentrantLockDemo demo=new ReentrantLockDemo(5);
        Thread t1=new Thread(() -> {
            System.out.println("foo");
        });

        Thread t2=new Thread(() -> {
            System.out.println("bar");
        });

        new Thread(() -> {
            try {
                demo.foo(t1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            try {
                demo.bar(t2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }


}
